<template>
  <div class="mt-3 mx-5" style="width:600px">
    <h2>Midas Gts Exporter</h2>
    <div class="mt-2">
      <p>本程序用于将Midas GTS NX所导出的FPN文件（包含了GTS软件的有限元模型网格模型数据）转换为FLAC3D 6.0或ABAQUS软件所使用的网格模型文件，以便于通过Midas GTS建模，然后通过FLAC3D 6.0或ABAQUS软件进行数值分析。</p>
    </div>

    <div class="mt-2">
      <b-form-file v-model="selectedFile" :state="Boolean(selectedFile)" placeholder="选择Midas Gts FPN 文件..." accept=".fpn, .txt"></b-form-file>
      <span v-if="selectedFile">
        <p>File name: {{selectedFile.name}}; File size: {{formatFileSize(selectedFile.size)}}</p>
      </span>

      <div class="row align-items-center">
        <div class="ml-3 mt-1 pt-2 px-2 border border-primary col-9">
          <b-form-group label="输出格式:">
            <b-form-radio-group v-model="exportType" :options="exportFormats"></b-form-radio-group>
          </b-form-group>
        </div>
        <div class="col">
          <b-button variant="primary" @click="onReadFile">读取并转换</b-button>
        </div>
      </div>
      
      <b-progress class="my-2" :value="readingProgress" :max="100" show-progress animated variant="success"></b-progress>

      <div v-if="showFileDownload" class="row mx-2">
        <p>{{ exportType==="flac3d"? "FLAC3D 6.0 网格与几何数据文件":"ABAQUS网格数据文件" }}</p>
        <b-button variant="success" size="sm" class="ml-auto" @click="onWriteFile">保存生成的网格文件...</b-button>
      </div>

      <pre v-if="meshCountInfo" class="mt-2 pt-2 border border-primary">{{ meshCountInfo.join("\r\n") }}</pre>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { List } from 'linqts';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';
import { WorkerMessageType, WorkerMessage } from '@/lib/WorkerMessage';
import Worker from 'worker-loader!./../lib/GtsExporter.Worker';
import { WebFileReader, WebFileWriter, OpenFileSelectDialog } from '@/lib/webFile';
import { AbaqusFileContent } from '@/lib/Abaqus/AbaqusData';
import { Flac3dFileContent } from '@/lib/Flac3d/Flac3dData';

@Component({
  components: {}
})
export default class GtsExporter extends Vue {
  private exportFormats = [{ text: 'FLAC3D 6.0', value: 'flac3d' }, { text: 'ABAQUS', value: 'abaqus' }];

  private fileData: string | null = null;
  private flac3dFileContent: Flac3dFileContent | null = null;
  private abaqusFileContent: AbaqusFileContent | null = null;
  private meshCountInfo: string[] | null = null;

  private selectedFile: File | null = null;
  private readingProgress = 0;
  private writingProgress = 0;

  private exportType: string = 'flac3d';

  //
  // properties
  //
  private get showFileDownload(): boolean {
    return this.flac3dFileContent != null || this.abaqusFileContent != null;
  }

  //
  // methods
  //
  private formatFileSize(fileSize: number): string {
    const KB = 1024;
    const MB = 1024 * 1024;
    const GB = 1024 * 1024 * 1024;
    if (fileSize >= GB) {
      return (fileSize / GB).toFixed(2) + ' GB';
    } else if (fileSize >= MB) {
      return (fileSize / MB).toFixed(2) + ' MB';
    } else if (fileSize >= KB) {
      return (fileSize / KB).toFixed(2) + ' KB';
    } else {
      return fileSize.toString() + ' byte';
    }
  }

  //
  // event handlers
  //
  private onReadFile(): void {
    if (!this.selectedFile) {
      return;
    }

    this.fileData = null;
    this.flac3dFileContent = null;
    this.abaqusFileContent = null;
    this.meshCountInfo = null;

    const reader = new WebFileReader(
      this.selectedFile,
      fileData => {
        // onCompleted
        this.fileData = fileData;
        this.parseFileData();
      },
      progress => {
        // onProgressChanged
        this.readingProgress = progress;
      }
    );
    reader.startReading();
  }

  private parseFileData() {
    if (!this.fileData) {
      return;
    }

    const worker = new Worker();
    worker.onmessage = event => {
      const message = event.data as WorkerMessage;
      if (message.messageType === WorkerMessageType.Progressing) {
        const progress = message.messageData as number;
        this.readingProgress = progress;
      } else if (message.messageType === WorkerMessageType.Completed) {
        this.readingProgress = 100;
        console.log('Parent: Receiving result ...');
        if (this.exportType === 'flac3d') {
          this.flac3dFileContent = message.messageData as Flac3dFileContent;
          this.meshCountInfo = this.flac3dFileContent.MeshCountInfo;
        } else if (this.exportType === 'abaqus') {
          this.abaqusFileContent = message.messageData as AbaqusFileContent;
          this.meshCountInfo = this.abaqusFileContent.MeshCountInfo;
        }
      } else if (message.messageType === WorkerMessageType.ErrorOccured) {
        console.log('Error occured while processing data ...');
      }
    };

    console.log('Parent: Start worker ...');
    if (this.exportType === 'flac3d') {
      worker.postMessage({
        messageType: WorkerMessageType.ExportFlac3d,
        messageData: this.fileData
      });
    } else if (this.exportType === 'abaqus') {
      worker.postMessage({
        messageType: WorkerMessageType.ExportAbaqus,
        messageData: this.fileData
      });
    }
  }

  private onWriteFile(): void {
    if (this.exportType === 'flac3d' && this.flac3dFileContent != null) {
      console.log('Writing result as zip file ...');
      const zip = new JSZip();
      const gridContent = this.flac3dFileContent.GridFileContent.join('\r\n');
      zip.file('gtsModel_Grid.f3grid', gridContent);
      const geomContent = this.flac3dFileContent.GeomFileContent.join('\r\n');
      zip.file('gtsModel_Geom.geom', geomContent);
      zip.generateAsync({ type: 'blob' }).then(blob => {
        saveAs(blob, 'gtsModel_flac3d.zip');
      });
    } else if (this.exportType === 'abaqus' && this.abaqusFileContent != null) {
      console.log('Writing result as zip file ...');
      const zip = new JSZip();
      const gridContent = this.abaqusFileContent!.MeshFileContent.join('\r\n');
      zip.file('gtsModel.inp', gridContent);
      zip.generateAsync({ type: 'blob' }).then(blob => {
        saveAs(blob, 'gtsModel_abaqus.zip');
      });
    }
  }
}
</script>
